﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace quizzer_linq_3
{
    /**Class: Administration
     * @author Samuel McCravy, Jayson Park
     * @version 1.1
     * Course : ITEC 4860 Spring 2012
     * Written: March 22, 2012
     * 
     * This Class lets admins add/remove users and categories.
     * 
     * Purpose: The purpose of this class is to ensure that all adding and removing of professors and categories is handled correctly.
    */

    public partial class Administration : Form
    {
        //This is a constant used to lookup any main ID(Questions, Professors, Subcategories, etc)

        const int MAIN_ID_LOOKUP_INDEX = 0;

        //This is a constant used to lookup the subcategory ID underneath the questions

        const int QUESTION_SUBCATEGORY_ID_LOOKUP_INDEX = 1;

        //This is a constant used to lookup the category name

        const int CATEGORY_NAME_LOOKUP_INDEX = 1;

        //This is a constant used to lookup the category name

        const int CATEGORY_ID_LOOKUP_INDEX = 0;

        //This is a constant used to lookup professor's email

        const int PROFESSOR_EMAIL_LOOKUP_INDEX = 3;

        //This is a constant used to lookup professor ID with relation to a specific question

        const int QUESTION_PROFESSOR_LOOKUP_INDEX = 13;

        //When pulling from the QDB using getCategoryForSubcategory methods, this is the index for the 
        //subcategory id when splitting the returned string using the '|' delimiter.

        const int QUIZZERDB_CAT_SUBCAT_SUBCATEGORYID_INDEX = 0;

        //When pulling from the QDB using getCategoryForSubcategory methods, this is the index for the 
        //subcategory name when splitting the returned string using the '|' delimiter.

        const int QUIZZERDB_CAT_SUBCAT_SUBCATEGORY_NAME_INDEX = 1;

        //When pulling from the QDB using getCategoryForSubcategory methods, this is the index for the 
        //category id when splitting the returned string using the '|' delimiter.

        const int QUIZZERDB_CAT_SUBCAT_CATEGORYID_INDEX = 2;

        //When pulling from the QDB using getCategory methods, this is the index for the 
        //category id when splitting the returned string using the '|' delimiter.

        const int QUIZZERDB_CATEGORY_CATEGORYID_INDEX = 0;

        //Checks to see if there is a blank category field when trying to remove a category

        Boolean blankCategoryToRemove = false;

        //Checks to see if there is a blank category field when trying to add a subcategory

        Boolean blankCategoryToAddSubcategory = false;

        //Checks to see if there is a blank category field when trying to remove a subcategory

        Boolean blankCategoryToRemoveSubcategory = false;

        //To access the database

        Quizzer_Data_Access dataAccess = new Quizzer_Data_Access();

        public Administration()
        {
            InitializeComponent();
            populateCategoryComboBoxes();
        }

        /** Method: adminBackButton_Click
         * Goes back to the admin menus
         * 
         * @param sender sender of the action
         * @param e event is triggered
        */

        private void adminBackButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /** Method: addProfessorButton_Click
         * Adds a new professor to the database
         * 
         * @param sender sender of the action
         * @param e event is triggered
        */

        private void addProfessorButton_Click(object sender, EventArgs e)
        {
            //This gets the first name from the textbox on the form near the add button under user maintance

            string firstName = (string)textBoxFirstName.Text;

            //This gets the last name from the textbox on the form near the add button under user maintance

            string lastName = (string)textBoxLastName.Text;

            //This gets the email from the textbox on the form near the add button under user maintance

            string email = (string)textBoxEmail.Text;

            //This gets the password from the textbox on the form near the add button under user maintance

            string password = (string)textBoxPassword.Text;

            //This variable is used for if the professor is in the database already or not

            Boolean checkEmail = false;

            //This checks to see if the professor is already in the database

            try
            {

                //Gets all the professors and puts them into an array

                String[] getDatabase = dataAccess.GetAllProfessor().Split('\n');
                for (int counter = 0; counter < getDatabase.Length - 1; counter++)
                {
                    //Gets all the professors from the other array and seperates there entries into a new array

                    String[] checkUsername = ((String)(getDatabase.GetValue(counter))).Split('|');

                    //Checks to see if their are duplicate emails/usernames

                    if (email.ToUpper().Equals(((string)checkUsername.GetValue(PROFESSOR_EMAIL_LOOKUP_INDEX)).ToUpper()))
                    {
                        checkEmail = true;
                    }
                }

            }
            catch (Exception caught)
            {
                Console.WriteLine("Something is wrong with the database");
                System.Diagnostics.EventLog.WriteEntry("Database search failed.", caught.StackTrace,
                   System.Diagnostics.EventLogEntryType.Warning);
            }

            /**This checks to make sure none of the boxes are empty and that the email contains the @ symbol
             * It then tries to add the new professor to the database
            */

            if (firstName.Length > 0 && lastName.Length > 0 && email.Contains("@") && password.Length > 0 && !checkEmail)
            {
                try
                {
                    dataAccess.NewProfessor(firstName, lastName, email, password);
                    textBoxFirstName.Text = "";
                    textBoxLastName.Text = "";
                    textBoxEmail.Text = "";
                    textBoxPassword.Text = "";
                    MessageBox.Show("Professor Added", "Successful Add");
                }
                catch (Exception caught)
                {
                    MessageBox.Show("Professor Adding Error has Occurred, Please make sure all fields are filled out correctly.", "Error!");
                    System.Diagnostics.EventLog.WriteEntry("Database write failed.", caught.StackTrace,
                   System.Diagnostics.EventLogEntryType.Warning);
                }
            }
            else
            {
                MessageBox.Show("Please make sure all fields have information in them and that a unique email(username) has been entered", "Error!");
            }

        }

        /** Method: removeProfessorButton_Click
         * Deletes a professor from the database
         * 
         * @param sender sender of the action
         * @param e event is triggered
        */

        private void removeProfessorButton_Click(object sender, EventArgs e)
        {

            //This gets the first name from the textbox on the form near the remove button

            string profEmail = (string)textBoxRemoveUserEmail.Text;

            /**This checks to make sure none of the boxes are empty
             * It then tries to remove the professor to the database
            */

            if (profEmail.Length > 0)
            {

                DialogResult dialogResult = MessageBox.Show("Are you sure you wish to remove this professor?\n" +
                    "\n(All questions related to this will be deleted as well).", "Confirmation", MessageBoxButtons.YesNo);
                if (dialogResult == DialogResult.Yes)
                {
                    if (checkValidEmailToRemove(profEmail))
                    {
                        removeProfessor(profEmail);
                        textBoxRemoveUserEmail.Text = "";
                    }
                    else
                    {
                        MessageBox.Show("Email address not found!", "Error!");
                    }
                }
            }
            else
            {
                MessageBox.Show("Email field is empty\nPlease enter in a valid email address.", "Error!");
            }
        }

        /**Method: checkValidEmailToRemove
         * @author Jayson Park
         * Checks to see if the email is within the database.
         * @param email the email to check in the database.
         * @return whether the email is in the database.
         */

        private Boolean checkValidEmailToRemove(string email)
        {
            string emailToCheck = (string)dataAccess.GetProfessor(email).Split('|').GetValue(MAIN_ID_LOOKUP_INDEX);
            if (emailToCheck.Trim() == "")
            {
                return (false);
            }
            return (true);
        }

        /** Method: removeProfessor
         * Deletes a professor from the database by email address
         * @author Jayson Park, Samuel McCravy
         * @param profEmail the email address of the professor to remove
        */

        private void removeProfessor(string profEmail)
        {
            //Gets the professors Id so we can delete all questions associated with him

            int profID = int.Parse(dataAccess.GetProfessor(profEmail).Split('|').GetValue(MAIN_ID_LOOKUP_INDEX).ToString());
            //Gets all the questions so we can sort them and remove the ones with the correct ID

            String[] getAllQuestions = dataAccess.GetAllQuestion().Split('\n');
            //Deletes all questions associated with profID

            for (int counter = 0; counter < getAllQuestions.Length - 1; counter++)
            {
                String[] getQuestion = ((String)getAllQuestions.GetValue(counter)).Split('|');
                if (profID == int.Parse(getQuestion.GetValue(QUESTION_PROFESSOR_LOOKUP_INDEX).ToString()))
                {
                    dataAccess.DeleteQuestion(int.Parse(getQuestion.GetValue(MAIN_ID_LOOKUP_INDEX).ToString()));
                }
            }
            dataAccess.DeleteProfessor(profEmail);
            MessageBox.Show("Professor and Questions Deleted", "Successful Deletion");
        }

        /** Method: addCategoryButton_Click
         * Adds a new category to the database
         * 
         * @param sender sender of the action
         * @param e event is triggered
        */

        private void addCategoryButton_Click(object sender, EventArgs e)
        {

            //This gets the category name from the textbox underneath the category maintance next to the add button on the form

            string catName = (string)textBoxNewCategory.Text;

            /**This checks to make sure none of the boxes are empty
             *It then tries to add a new category to the database
            */

            if (catName.Length > 0)
            {
                if (duplicateCategory(catName))
                {
                    MessageBox.Show("Category already exists!", "Error!");
                }
                else
                {
                    dataAccess.NewCategory(catName);
                    MessageBox.Show("Category Added", "Successful Add");
                    textBoxNewCategory.Text = "";
                    populateCategoryComboBoxes();
                    blankCategoryToAddSubcategory = false;
                    blankCategoryToRemove = false;
                }
            }
            else
            {
                MessageBox.Show("Fields Empty, Please make sure all fields have the correct information", "Error!");
            }
        }

        /** Method: duplicateCategory
         * @author Jayson Park
         * Checks to see if the category is already within the database
         * 
         * @param category the category name
        */

        private Boolean duplicateCategory(string category)
        {
            string[] categories = dataAccess.GetAllCategory().Split('|');
            for (int catCounter = 0; catCounter < categories.Length; catCounter++)
            {
                if (categories[catCounter].ToUpper().Trim().Equals(category.ToUpper()))
                {
                    return (true);
                }
            }
            return (false);
        }

        /** Method: removeCategoryButton_Click
         * Deletes a category from the database
         * 
         * @param sender sender of the action
         * @param e event is triggered
        */

        private void removeCategoryButton_Click(object sender, EventArgs e)
        {
            if (comboBoxPickCategoryAdd.Items.Count > 0)
            {
                //Gets the selected category
                string catName = ((string)comboBoxPickCategoryAdd.SelectedItem).Trim();
                if (blankCategoryToRemove == false)
                {
                    //Shows a dialog box to confirm removal of category and then executes deletion of categories and subcategories and questions associated with them

                    DialogResult dialogResult = MessageBox.Show("Are you sure you wish to remove this category?\n" +
                        "\nAll questions and sub-categories related to this will be deleted as well.", "Confirmation", MessageBoxButtons.YesNo);
                    if (dialogResult == DialogResult.Yes)
                    {
                        deleteSubCategoriesAndQuestions(catName);
                        dataAccess.DeleteCategory(catName);
                        MessageBox.Show("Category, Subcategories, and Questions Deleted", "Successful Deletion");
                    }
                    populateCategoryComboBoxes();
                }
                else
                {
                    MessageBox.Show("Category Deletion Error has Occurred, please make sure a category is selected.", "Error!");
                }
            }
            else
            {
                MessageBox.Show("No categories found!\nPlease add a category first!", "Error!");
            }
        }

        /** Method: buttonAddSubcategory_Click
         * Adds a subcategory to an existing category
         * 
         * @param sender sender of the action
         * @param e event is triggered
        */

        private void buttonAddSubcategory_Click(object sender, EventArgs e)
        {
            if (comboBoxCategorySub.Items.Count > 0)
            {
                //This gets the category from the textbox under category maintance next to the second add button

                string categoryTextbox = ((string)comboBoxCategorySub.SelectedItem).Trim();

                //This gets the subcategory name from the textbox under category maintance next to the second add button

                string subcategoryName = ((string)textBoxSubcategoryName.Text).Trim();

                addSubcategory(categoryTextbox, subcategoryName);
            }
            else
            {
                MessageBox.Show("No categories found!\nPlease add a category first!", "Error!");
            }
        }

        /** Method: buttonAddSubcategory_Click
         * Adds a subcategory to an existing category
         * 
         * @param categoryName the name of the category to add the subcategory to
         * @param subcategoryName the name for the subcategory that is being added
        */
        private void addSubcategory(string categoryName, string subcategoryName)
        {
            if (subcategoryName.Length > 0)
            {
                if (duplicateSubcategory(subcategoryName, categoryName))
                {
                    MessageBox.Show("Subcategory already exists within the Category", "Error!");
                }
                else if (blankCategoryToAddSubcategory == false)
                {
                    //This is for the category ID

                    int categoryID = int.Parse(((string)dataAccess.GetCategory(categoryName.Trim()).Split('|').GetValue(MAIN_ID_LOOKUP_INDEX)));
                    dataAccess.NewSubCategory(subcategoryName, categoryID);
                    textBoxSubcategoryName.Text = "";
                    populateCategoryComboBoxes();
                    MessageBox.Show("Subcategory Created", "Successful Creation");
                }
                else
                {
                    MessageBox.Show("Subcategory Adding Error has Occurred, please make sure a category is selected.", "Error!");
                }
            }
            else
            {
                MessageBox.Show("Subcategory cannot have a blank name!", "Error!");
            }
        }

        /** Method: duplicateSubcategory
         * @author Jayson Park
         * Checks to see if the subcategory is within the passed category
         * 
         * @param subcategory the subcategory string to check
         * @param category the category check to see if the passed subcategory already exists within the category
        */

        private Boolean duplicateSubcategory(string subcategory, string category)
        {
            int categoryID = Convert.ToInt32(dataAccess.GetCategory(category).Split('|').GetValue(CATEGORY_ID_LOOKUP_INDEX));
            string[] subcategories = dataAccess.GetSubCategoryForCategory(categoryID).Split('|');
            for (int subcatCounter = 0; subcatCounter < subcategories.Length; subcatCounter++)
            {
                if (subcategories[subcatCounter].ToUpper().Trim().Equals(subcategory.ToUpper()))
                {
                    return (true);
                }
            }
            return (false);
        }

        /** Method: populateCategoryComboBox
         * @author Jayson Park, Samuel McCravy
         * Populates the category combo boxes with categories
        */

        private void populateCategoryComboBoxes()
        {
            String[] getAllCategories = dataAccess.GetAllCategory().Split('\n');

            comboBoxCategorySub.Items.Clear();
            comboBoxPickCategoryAdd.Items.Clear();
            comboBoxCategorySubRemove.Items.Clear();
            String[] getCategory;

            for (int counter = 0; counter < getAllCategories.Length - 1; counter++)
            {
                getCategory = ((String)(getAllCategories.GetValue(counter))).Split('|');
                comboBoxPickCategoryAdd.Items.Add(getCategory.GetValue(CATEGORY_NAME_LOOKUP_INDEX));
                comboBoxCategorySub.Items.Add(getCategory.GetValue(CATEGORY_NAME_LOOKUP_INDEX));
                comboBoxCategorySubRemove.Items.Add(getCategory.GetValue(CATEGORY_NAME_LOOKUP_INDEX));
            }
            defaultCategoryComboBoxesSelection();
            sendCategoryIDForSubcategory();
        }

        /**Method; sendCategoryIDForSubcategory
         * This finds the current category ID for the category under "Remove Subcategory"
         * Then sends it to the populateRemoveSubcategoryComboBox method to update the subcategories to remove
         */

        private void sendCategoryIDForSubcategory()
        {
            int currentCategoryID;

            if (comboBoxCategorySubRemove.Items.Count > 0)
            {
                currentCategoryID = Convert.ToInt32(dataAccess.GetCategory(((string)comboBoxCategorySubRemove.SelectedItem).Trim()).
                     Split('|').GetValue(QUIZZERDB_CATEGORY_CATEGORYID_INDEX));
            }
            else
            {
                currentCategoryID = 0;
            }
            populateRemoveSubcategoryComboBox(currentCategoryID);
        }

        /** Method: populateCategoryComboBox
         * @author Jayson Park
         * Populates the category combo boxes with categories
        */

        private void populateRemoveSubcategoryComboBox(int currentRemoveCategory)
        {
            comboBoxSubcategorySubRemove.Items.Clear();

            String[] subCategories = dataAccess.GetSubCategoryForCategory(currentRemoveCategory).Split('\n');

            for (int subCategoryCounter = 0; subCategoryCounter < subCategories.Length - 1; subCategoryCounter++)
            {
                comboBoxSubcategorySubRemove.Items.Add(((String)(subCategories.GetValue(subCategoryCounter))).Split('|').GetValue(QUIZZERDB_CAT_SUBCAT_SUBCATEGORY_NAME_INDEX));
            }
            if (comboBoxSubcategorySubRemove.Items.Count > 0)
            {
                comboBoxSubcategorySubRemove.SelectedIndex = 0;
            }
        }

        /** Method: populateCategoryComboBox
         * @author Jayson Park
         * Sets the default category combo boxes to the initial selection unless there isn't any selections in the combo box which
         * will set a flag stating that there are no elements within the combo box. 
        */

        private void defaultCategoryComboBoxesSelection()
        {
            blankCategoryToRemove = false;
            if (comboBoxPickCategoryAdd.Items.Count > 0)
            {
                comboBoxPickCategoryAdd.SelectedIndex = 0;
            }
            else
            {
                blankCategoryToRemove = true;
            }

            blankCategoryToAddSubcategory = false;
            if (comboBoxCategorySub.Items.Count > 0)
            {
                comboBoxCategorySub.SelectedIndex = 0;
            }
            else
            {
                blankCategoryToAddSubcategory = true;
            }

            blankCategoryToRemoveSubcategory = false;
            if (comboBoxCategorySubRemove.Items.Count > 0)
            {
                comboBoxCategorySubRemove.SelectedIndex = 0;
            }
            else
            {
                blankCategoryToRemoveSubcategory = true;
            }
        }

        /** Method: deleteSubCategoriesAndQuestions
         * Deletes subcategories for selected category name
         * 
        */

        private void deleteSubCategoriesAndQuestions(String catName)
        {
            //Gets the ID for the category so you can lookup the sub categories
            int catID = int.Parse((string)dataAccess.GetCategory(catName).Split('|').GetValue(0));

            //Gets all the subcategories

            String[] subCategories = dataAccess.GetSubCategoryForCategory(catID).Split('\n');

            //Deletes questions and subcategories

            int subCatID;

            for (int subcounter = 0; subcounter < subCategories.Length - 1; subcounter++)
            {
                subCatID = int.Parse((String)((String)subCategories.GetValue(subcounter)).Split('|').GetValue(MAIN_ID_LOOKUP_INDEX));
                deleteQuestionsFromSubcategory(subCatID);
                dataAccess.DeleteSubCategory(subCatID);
            }
        }

        /** Method: removeQuestionsFromSubcategory
         * @author Jayson Park
         * Removes the questions within the given subcategory
         * @param subCatID the subcategory ID to remove questions from
        */

        private void deleteQuestionsFromSubcategory(int subCatID)
        {
            String[] getAllQuestions = dataAccess.GetAllQuestion().Split('\n');
            String[] getQuestion;
            int questionID;
            for (int questioncounter = 0; questioncounter < getAllQuestions.Length - 1; questioncounter++)
            {
                //Gets the individual questions

                getQuestion = ((String)getAllQuestions.GetValue(questioncounter)).Split('|');
                if (int.Parse(getQuestion.GetValue(QUESTION_SUBCATEGORY_ID_LOOKUP_INDEX).ToString()) == subCatID)
                {
                    questionID = int.Parse(getQuestion.GetValue(MAIN_ID_LOOKUP_INDEX).ToString());
                    deleteQuestionsFromGameSets(questionID);
                    dataAccess.DeleteQuestion(questionID);
                }
            }
        }

        /** Method: deleteQuestionsFromGameSets
         * @author Jayson Park
         * Removes the question_gameset entries for the given question
         * @param questionID the question ID to remove from question_gameset
        */

        private void deleteQuestionsFromGameSets(int questionID)
        {
            String[] getAllGameSetWithQuestion = (dataAccess.gameSetWithQuestion(questionID).Trim()).Split('\n');
            int gameSetID;
            for (int gameSetCounter = 0; gameSetCounter < getAllGameSetWithQuestion.Length; gameSetCounter++)
            {
                if (((String)getAllGameSetWithQuestion.GetValue(gameSetCounter)).Trim() != "")
                {
                    gameSetID = int.Parse(((String)getAllGameSetWithQuestion.GetValue(gameSetCounter)).Trim());
                    dataAccess.removeFromGameset(questionID, gameSetID);
                }
            }
        }

        /** Method: buttonRemoveSubcategory_Click
         * Checks to see if a subcategory exists
         * 
         * @param sender sender of the action
         * @param e event is triggered
        */

        private void buttonRemoveSubcategory_Click(object sender, EventArgs e)
        {
            if (comboBoxSubcategorySubRemove.Items.Count > 0)
            {
                if (blankCategoryToRemoveSubcategory == false)
                {
                    String categoryName = ((String)comboBoxCategorySubRemove.SelectedItem).Trim();
                    int catID = int.Parse((String)dataAccess.GetCategory(categoryName).Trim().Split('|').GetValue(MAIN_ID_LOOKUP_INDEX));
                    String[] subcategories = dataAccess.GetSubCategoryForCategory(catID).Trim().Split('\n');
                    String[] subcategory;
                    int subCatID = 0;
                    for (int subcatCounter = 0; subcatCounter < subcategories.Length; subcatCounter++)
                    {
                        subcategory = subcategories.GetValue(subcatCounter).ToString().Trim().Split('|');
                        if (int.Parse((String)subcategory.GetValue(QUIZZERDB_CAT_SUBCAT_CATEGORYID_INDEX)) == catID)
                        {
                            subCatID = int.Parse((String)subcategory.GetValue(QUIZZERDB_CAT_SUBCAT_SUBCATEGORYID_INDEX));
                        }
                    }
                    removeSubcategory(subCatID);
                }
                else
                {
                    MessageBox.Show("Subcategory Deletion Error has Occurred, please make sure a category is selected.", "Error!");
                }
            }
            else
            {
                MessageBox.Show("No subcategories found!\nPlease add a subcategory first!", "Error!");
            }
        }

        /** Method: removeSubcategory
         * @author Jayson Park
         * Removes an existing subcategory from the category
         * @param subCatID the subcategory ID to remove
        */

        private void removeSubcategory(int subCatID)
        {

            DialogResult dialogResult = MessageBox.Show("Are you sure you wish to remove this subcategory?\n" +
                "\nAll questions related to this will be deleted as well.", "Confirmation", MessageBoxButtons.YesNo);
            if (dialogResult == DialogResult.Yes)
            {
                deleteQuestionsFromSubcategory(subCatID);
                dataAccess.DeleteSubCategory(subCatID);
                MessageBox.Show("Subcategory and Questions Deleted", "Successful Deletion");
            }
            populateCategoryComboBoxes();

        }

        /** Method: comboBoxCategorySubRemove_SelectedIndexChanged
         * Updates the subcategory when a category is changed
         * 
         * @param sender sender of the action
         * @param e event is triggered
        */

        private void comboBoxCategorySubRemove_SelectedIndexChanged(object sender, EventArgs e)
        {
            sendCategoryIDForSubcategory();
        }
    }
}
